package com.kaka.jsonmap.core.evaluator;

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.kaka.jsonmap.core.evaluator.GlobalJsonPathEvaluator.JSONPATH_ROOT;

@Slf4j
public abstract class JsonPathEvaluator implements ExpressionEvaluator {


    private static final Pattern INDEX_PATTERN = Pattern.compile("^(.*?\\[\\d+])(.*)$");

    @Override
    public Object evaluate(String expression, Map<String, Object> context) {
        if (context == null) {
            log.debug("Context is null for JSONPath: {}", expression);
            return null;
        }

        log.debug("Evaluating JSONPath: {}", expression);
        Matcher matcher = INDEX_PATTERN.matcher(expression);
        if (matcher.matches()) {
            return evaluateIndexedPath(expression, matcher, context);
        } else {
            return evaluateSimplePath(expression, context);
        }
    }

    // 未测试
    private Object evaluateSimplePath(String expression, Map<String, Object> context) {
        try {
            return JsonPath.read(context, expression);
        } catch (PathNotFoundException e) {
            log.debug("Path not found for JSONPath: {}", expression);
            return null; // 路径不存在时返回 null，不记录警告日志
        } catch (Exception e) {
            log.warn("Failed to evaluate JSONPath: {}, error: {}", expression, e.getMessage());
            return null;
        }
    }

    private Object evaluateIndexedPath(String expression, Matcher matcher, Map<String, Object> context) {
        String indexedPath = matcher.group(1); // 包含索引的部分，例如 $.addressList[?(@.addrType == 'H')][0]
        String remainingPath = matcher.group(2); // 后续字段，例如 .addrProvinceCode

        // 解析索引部分
        String[] parts = indexedPath.split("\\[");
        String basePath = parts[0]; // $.addressList[?(@.addrType == 'H')]
        Object currentResult = null;
        Map<String, Object> currentContext = context;

        for (int i = 1; i < parts.length; i++) {
            String segment = parts[i].substring(0, parts[i].length() - 1); // 去掉 ]
            if (segment.matches("\\d+")) {
                int index = Integer.parseInt(segment);
                currentResult = evaluateBasePath(basePath, currentContext);
                if (!(currentResult instanceof List)) {
                    log.debug("Path {} did not return a list, cannot apply index {}, result: {}", basePath, index, currentResult);
                    return null;
                }
                List<?> list = (List<?>) currentResult;
                if (list.isEmpty()) {
                    log.debug("Path {} returned empty list, index {} unavailable", basePath, index);
                    return null;
                }
                if (index < 0 || index >= list.size()) {
                    log.debug("Index {} out of bounds for path {}, list size: {}", index, basePath, list.size());
                    return null;
                }
                currentResult = list.get(index);
                currentContext = currentResult instanceof Map ? (Map<String, Object>) currentResult : null;
                basePath = null; // 重置 basePath，接下来处理对象
            } else {
                basePath = basePath + "[" + segment + "]"; // 重新拼接非数字索引（如过滤器）
            }
        }

        // 处理剩余的字段访问
        if (remainingPath != null && !remainingPath.isEmpty()) {
            if (currentContext == null) {
                log.debug("No valid context to apply remaining path: {}", remainingPath);
                return null;
            }
            try {
                return JsonPath.read(currentContext, JSONPATH_ROOT + remainingPath);
            } catch (PathNotFoundException e) {
                log.debug("Path not found for remaining JSONPath: {}", remainingPath);
                return null;
            } catch (Exception e) {
                log.warn("Failed to evaluate remaining JSONPath: {}, error: {}", remainingPath, e.getMessage());
                return null;
            }
        }

        return currentResult;
    }

    private Object evaluateBasePath(String basePath, Map<String, Object> context) {
        try {
            return JsonPath.read(context, basePath);
        } catch (PathNotFoundException e) {
            log.debug("Path not found for base JSONPath: {}", basePath);
            return null;
        } catch (Exception e) {
            log.warn("Failed to evaluate base JSONPath: {}, error: {}", basePath, e.getMessage());
            return null;
        }
    }
}
